package org.bookie.model.services.impl;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.bookie.model.BetSlip;
import org.bookie.model.Comment;
import org.bookie.model.Transaction;
import org.bookie.model.Wager;
import org.bookie.model.services.RepaymentService;
import org.hibernate.Session;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

public class RepaymentServiceImpl implements RepaymentService {
	private Session session;
	private Log log; 
	
	@SuppressWarnings("unchecked")
	public Set<String> repay() {
		Set<String> result = new HashSet<String>();
		List<Wager> wagers = session.createCriteria(Wager.class)
						.add(Restrictions.eqProperty("bet.successfulOutcome", "outcome"))
							.createCriteria("outcome", "outcome")
								.createCriteria("bet", "bet")
										.list();
		for(Wager w:wagers){
			BetSlip bs = w.getBetSlip();
			if (bs.isSuccessful()) {
				boolean isNull = isProfitNull(bs);
				if(isNull){
					bs.recalcProfit();
					session.saveOrUpdate(bs);
					saveTransaction(bs);
					result.add(bs.getUser().getUsername());
				}
			}
		}
		return result;
	}
	
	private void saveTransaction(BetSlip betSlip) {
		// Store a transaction only if the bet slip is closed
		if (betSlip.getProfit().equals(new Double(0))) {
			return;
		}
		betSlip.getUser().getAccount().deposit(betSlip);
	}
	
	private boolean isProfitNull(BetSlip bs){
		Object obj = session.createCriteria(Transaction.class)
						.setProjection(Projections.projectionList()
											.add(Projections.rowCount())
											.add(Projections.groupProperty("betSlip")))
						.add(Restrictions.eq("comment", Comment.PROFIT))
						.add(Restrictions.eq("betSlip", bs))
						.uniqueResult();
		return obj==null;
	}
	
	/**
	 * Injector method
	 * @category injector
	 * @param s
	 */
	@SuppressWarnings("unchecked")
	public void setSession(Session s) {
		this.session = s;
	}
	
	/**
	 * Setter for the log service
	 * 
	 * @category injector
	 * @param log
	 */
	public void setLog(Log log) {
		this.log = log;
	}

}
